//////////////////////////////////////////////////////////////////////////////
//
//  access_det.v
//
//  访问检测模块。产生确认信号ack，反馈给TAP控制器。
//
//  Original Author: 
//  Current Owner:   
//
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015 Synopsys, Inc.  All rights reserved.
//
// SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of
// Synopsys, Inc., and is fully protected under copyright and trade secret
// laws.  You may not view, use, disclose, copy, or distribute this file or
// any information contained herein except pursuant to a valid written
// license agreement. It may not be used, reproduced, or disclosed to others
// except in accordance with the terms and conditions of that agreement.
//
//////////////////////////////////////////////////////////////////////////////
//
//    Perforce Information
//    $Author:  
//    $File:  /rtl/np_access_det.v $
//    $DateTime:  
//    $Revision:  
//
//////////////////////////////////////////////////////////////////////////////

`timescale 1ns/10fs
module np_access_det (
// Clock and Reset
input  wire              cfg_clk,
input  wire              cfg_rst,

// CFG input interfaces
input  wire [31:0]  cfg_addr,
input  wire [31:0]  cfg_wr_data,
input  wire         cfg_wr_en,
input  wire         cfg_rd_en,
output wire         cfg_ack,
output wire [31:0]  cfg_rd_data,

// CFG output interface
output wire [31:0]  cfg_addr_o,
output wire [31:0]  cfg_wr_data_o,
(*mark_debug = "true"*) output reg          cfg_wr_en_o,
(*mark_debug = "true"*) output reg          cfg_rd_en_o,
input  wire [31:0]  cfg_rd_data_i
);

// -------------------------
// Registers and nets
// -------------------------

reg  [31:0]    cfg_wr_data_d1;
reg            cfg_wr_en_d1;
reg            cfg_rd_en_d1;
reg            cfg_ack_int_d2;
reg            cfg_ack_int_d1;
(*mark_debug = "true"*) wire           cfg_ack_int;
(*mark_debug = "true"*) wire           cfg_access_det;
// Mantis 7117 - Fix LINT issues in cfg_access_det_d and cfg_arbt_addr_int_d1
reg  [31:0]     cfg_access_det_d;
reg            cfg_access_in_prog;
// 内部信号延迟一周期
always @(posedge cfg_clk or posedge cfg_rst) begin
  if (cfg_rst) begin
    cfg_wr_data_d1          <= 32'd0;
    cfg_wr_en_d1            <= 1'b0;
    cfg_rd_en_d1            <= 1'b0;
    cfg_ack_int_d1          <= 1'd0;
    cfg_ack_int_d2          <= 1'd0;
  end
  else begin
    cfg_wr_data_d1          <= cfg_wr_data;
    cfg_wr_en_d1            <= cfg_wr_en;
    cfg_rd_en_d1            <= cfg_rd_en;
    cfg_ack_int_d1          <= cfg_ack_int;
    cfg_ack_int_d2          <= cfg_ack_int_d1;
  end
end

// // ack与 rd_en或者wr_en 在同一周期产生
//   assign cfg_ack_int = (cfg_ack_int_d1 & cfg_rd_en) ? 1'b0 :
//                        cfg_wr_en ? ({cfg_access_det_d[3:0],cfg_access_det} == 5'b10000) :
//                        cfg_rd_en ? ({cfg_access_det_d[0],cfg_access_det} == 2'b10) : 1'b0;

// ack与 rd_en或者wr_en 在同一周期产生
// 检测n个clk后，访问到数据，此处为[7]为8，访问到数据后拉低
  assign cfg_ack_int = (cfg_ack_int_d1 & cfg_rd_en) ? 1'b0 :
                       cfg_wr_en ? ({cfg_access_det_d[3],cfg_access_det} == 2'b10) :
                       cfg_rd_en ? ({cfg_access_det_d[20],cfg_access_det} == 2'b10) : 1'b0;

// 在配置接口上检测访问请求 wr_en
always @(posedge cfg_clk or posedge cfg_rst) begin
  if (cfg_rst) begin
    cfg_access_det_d <= 31'd0;
    cfg_wr_en_o <= 1'b0; 
    cfg_rd_en_o <= 1'b0; 
  end
  else begin
    cfg_access_det_d[31:0] <= {cfg_access_det_d[30:0], cfg_access_det};
    cfg_wr_en_o <= cfg_wr_en & ({cfg_access_det_d[1:0],cfg_access_det} == 3'b100);
    cfg_rd_en_o <= cfg_rd_en & ({cfg_access_det_d[1:0],cfg_access_det} == 3'b100);
  end
end 
    
// 新的访问检测(暂时不考虑连续的情况)：
//  - wr_en或rd_en的上升沿
assign cfg_access_det = (~cfg_wr_en_d1 & cfg_wr_en) |
                       (~cfg_rd_en_d1 & cfg_rd_en);

// 正在进行配置访问标志
// cfg_ack_int优先，以确保ack同周期不置位cfg_access_in_prog。
always @(posedge cfg_clk or posedge cfg_rst) begin
  if (cfg_rst) begin
    cfg_access_in_prog <= 1'b0;
  end
  else begin
    if (cfg_ack_int == 1'b1)
      cfg_access_in_prog <= 1'b0;
    else if (cfg_access_det == 1'b1)
      cfg_access_in_prog <= 1'b1;
  end
end

assign cfg_ack = cfg_rd_en ? cfg_ack_int_d1 : cfg_ack_int;

assign cfg_rd_data = cfg_rd_data_i;

// -------------------------------------------
// 输出到配置总线
// -------------------------------------------

// The address goes through an additional flop stage after
// decoding into the 32 one-hot cfg_sel bank signals, so it
// should not be flopped here.
// 
assign cfg_addr_o    = cfg_addr;

// wr_data、wr_en和rd_en应翻转，以与翻转的cfg_sel信号对齐。
assign cfg_wr_data_o = cfg_wr_data_d1;


endmodule
